<?php
class Action {
    protected $actionPrefix = '';       #方法名称前缀
    protected $actionSuffix = '';       #方法名称后缀
    public static $isAjax = false;      #方法为AJAX调用
    protected $defaultAction = '';       #默认执行方法
    
    protected $authCheckPass = true;    #权限验证是否通过
    protected $authName = '';           #权限名称
    
    public function __construct() {}
    
    /**
     * 设置方法名称前缀
     */
    public function setPrefix($prefix = '') {
        $this->actionPrefix = $prefix;
    }
    
    /**
     * 设置方法名称后缀
     */
    public function setSuffix($suffix='') {
        $this->actionSuffix = $suffix;
    }
    
    /**
     * 表单令牌环，防止表单重复提交
     */
    protected function setFormToken() {
        Session::start();
        $tokenValue = md5(uniqid(mt_rand()));
        View::assign('tokenName', Config::get('VAR_TOKENNAME'));
        View::assign('tokenValue', $tokenValue);
        $_SESSION[Config::get('VAR_TOKENNAME')] = $tokenValue;
    }
    
    /**
     * 验证令牌环
     */
    protected function isValidToken() {
        Session::start();
        $sessToken = $_SESSION[Config::get('VAR_TOKENNAME')];
        $formToken = $_REQUEST[Config::get('VAR_TOKENNAME')];
        unset($_SESSION[Config::get('VAR_TOKENNAME')]);
        unset($_REQUEST[Config::get('VAR_TOKENNAME')]);
        if($sessToken != $formToken) {
            /*
            $formName = 'FORM_' . MODULE_NAME . '_' . ACTION_NAME;
            $formData = Session::get('formData');
            if($formData) $formData = unserialize($formData);
            $formData[$formName] = serialize($_REQUEST);
            Session::set('formData', serialize($formData));*/
            return false;
        }
        return true;
    }
    
    /**
     * AJAX返回数据，数据经JSON_ENCODE处理后返回
     */
    protected function ajaxReturn($returnData) {
        ob_clean();
        Config::set('DEBUG', false);
        echo json_encode($returnData);
        self::$isAjax = true;
    }
    
    /**
     * 文件数据返回
     * @param String $fileName      #下载文件名
     * @param String $contentTYpe   #文件MIME类型
     * @param array  $returnCfg     #返回内容设置数组,如使用本方法之前已输出文件内容，可不设置此参数
     *                              #contents:文件内容， 与filepath键二选一
     *                              #filepath:服务器文件实际路径，使用此参数时不需要设置 contents键
     * @return void
     */
    protected function returnFile($fileName, $contentType='application/octet-stream', $returnCfg=array()) {
        Config::set('DEBUG', false);
        self::$isAjax = true;
        
        header("Pragma:public");
        header("Expires:0");
        header("Content-type:" . $contentType . ';charset=utf-8');
        header("Accept-Ranges:bytes");
        if ('' != $returnCfg['contents']) {
            ob_clean();
            $fileSize = strlen($returnCfg['contents']);
        } else if ('' != $returnCfg['filepath']){
            ob_clean();
            $fileSize = filesize($returnCfg['filepath']);
        }
        if($fileSize > 0)
        header("Accept-Length:".$fileSize);
        $ua = $_SERVER['HTTP_USER_AGENT'];
        if(preg_match('/firefox/i', $ua)) {
            $fileName = str_replace('+', '%20', urlencode($fileName));
            $fileName = "utf8''" . $fileName;
            header("Content-Disposition:attachment; filename*=\"{$fileName}\"");
        } else if(preg_match('/msie/i', $ua)){
            $fileName = str_replace('+', '%20', urlencode($fileName));
            header("Content-Disposition:attachment; filename=\"{$fileName}\"");
        } else {
            header("Content-Disposition:attachment; filename=\"{$fileName}\"");
        }
        if ('' != $returnCfg['contents']) {
            echo $returnCfg['contents'];
        } else if('' != $returnCfg['filepath']) {
            if(preg_match('/apache/i', $_SERVER['SERVER_SOFTWARE'])) {
                echo file_get_contents($returnCfg['filepath']);
            } else if (preg_match('/lighttpd/i', $_SERVER['SERVER_SOFTWARE'])) {
                header('X-LIGHTTPD-Send-file:' . $returnCfg['filepath']);
            } else if (preg_match('/nginx/i', $_SERVER['SERVER_SOFTWARE'])) {
                $nginxSendfileMaps = Config::get('NGINS_SENDFILE_MAP');
                $filePath = $returnCfg['filepath'];
                foreach($nginxSendfileMaps as $map) {
                    if(0 === strpos($filePath, $map[0])) {
                        $filePath = str_replace($map[0], $map[1], $filePath);
                        break;
                    }
                }
                header('X-Accel-Redirect:' . $filePath);
            }
        }
        exit;
    }
    
    /**
     * @return mixed
     */
    public function __beforeExec() {}
    
    /**
     * @return void
     */
    public function __afterExec() {}
    
    /**
     * 设置模板名称
     * @return void
     */
    public function setTemplate($template, $tplDir=MODULE_NAME) {
        View::setTemplate($template, $tplDir);
    }

    /**
     * @param mixed $var
     * @param mixed $value
     * @return void
     */
    public function assign($var, $value='') {
        View::assign($var, $value);
    }
    
    /**
     * 清除所有模板赋值
     */
    public function clearAllAssign() {
        View::clearAllAssign();
    }
    
    /**
     * 权限校验
     * @return boolean
     */
    protected  function isAuthAction($authName, $isSuper=false, $ajaxAction = false) {
        $checkResult = SysAuth::checkAuth($authName, $isSuper);
        if (false == $checkResult) {
            $this->authCheckPass = false;
            $this->authName = $authName;
            self::$isAjax = $ajaxAction;
        }
        return $checkResult;
    }
    
    /**
     * 请求为表单POST
     */
    protected function isPost() {
        return 'POST' == $_SERVER['REQUEST_METHOD'];
    }
    
    /**
     * 正常请求，非表单POST
     */
    protected function isGet() {
        return 'GET' == $_SERVER['REQUEST_METHOD'];
    }

    /**
     * 执行用户动作
     */
    public function run() {
        $action = $this->defaultAction ? $this->defaultAction : ACTION_NAME;
        $actionName = $action . $this->actionSuffix;
        $actionPrefix = $this->actionPrefix;
        if ('' != $actionPrefix) {
            $actionName = $actionPrefix . ucfirst($actionName);
        }
        define('METHOD_NAME', $actionName);
        $this->__beforeExec();
        $actionResult = $this->$actionName();
        $this->__afterExec();

        if (is_object($actionResult)) {
            Config::set('DEBUG', false);
            $actionResult->run();
        } else {
            if (null !== $actionResult) {
                Config::set('DEBUG', false);
                $this->ajaxReturn($actionResult);
                
                if (Config::get('LOG_RESULT')) {
                    Logger::dumpToFile(RUNTIME_DIR . '/' . MODULE_NAME . '_' . ACTION_NAME, $actionResult);
                }
            } else {
                if(false == $this->authCheckPass) {
                    if (false == self::$isAjax) {
                        $redirect = new Redirect(Config::get('DENID_ACTION'), Config::get('DENID_MODULE'), 
                                        array('authName'=>$this->authName,
                                              'url'=>encodeUrl($_SERVER['HTTP_REFERER'])));
                        $redirect->run();
                    } else {
                        echo json_encode("对不起， 您没有“" . $this->authName . "”的权限");
                    }
                } else if (false == self::$isAjax) {
                        if('' == ob_get_contents()) {
                            if (Config::get('ENABLE_FORMTOKEN')) {
                                $this->setFormToken();
                            }
                            $contents = View::fetch();
                            echo $contents;
                        } else {
                            self::$isAjax = true;
                        }
                    }
                }
            }
        }
}
?>